package io.demo;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.NoAlertPresentException;
import org.openqa.selenium.WebDriver;

import java.util.Collection;
import java.util.Collections;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import static org.assertj.core.api.Fail.fail;

public abstract class SeleniumChromeTestBase {
    private WebDriver driver;
    private boolean acceptNextAlert = true;
    private StringBuilder verificationErrors = new StringBuilder();

    protected abstract WebDriver defineWebDriver();

    protected long defineImplicitWait() {
        return 30;
    }

    protected abstract String defineUrl();

    protected Collection<WebDriverAction> defineWebDriverActions() {
        return Collections.emptyList();
    }

    @Before
    public void setUp() {
        System.setProperty("webdriver.chrome.driver", ChromeDriverPath.SINGLE.get());
        driver = defineWebDriver();
        driver.manage().timeouts().implicitlyWait(defineImplicitWait(), TimeUnit.SECONDS);
    }

    @Test
    public void doTest() {
        driver.get(defineUrl());

        Optional.ofNullable(defineWebDriverActions())
                .orElse(Collections.emptyList())
                .forEach(webDriverAction -> webDriverAction.accept(driver));
    }


    @After
    public void tearDown() {
        driver.quit();
        String verificationErrorString = verificationErrors.toString();
        if (!"".equals(verificationErrorString)) {
            fail(verificationErrorString);
        }
    }

    protected boolean isElementPresent(By by) {
        try {
            driver.findElement(by);
            return true;
        } catch (NoSuchElementException e) {
            return false;
        }
    }

    protected boolean isAlertPresent() {
        try {
            driver.switchTo().alert();
            return true;
        } catch (NoAlertPresentException e) {
            return false;
        }
    }

    protected String closeAlertAndGetItsText() {
        try {
            Alert alert = driver.switchTo().alert();
            String alertText = alert.getText();
            if (acceptNextAlert) {
                alert.accept();
            } else {
                alert.dismiss();
            }
            return alertText;
        } finally {
            acceptNextAlert = true;
        }
    }
}

